package com.hsgene.consumables.service.impl;

import com.fasterxml.jackson.core.type.TypeReference;
import com.google.common.collect.Lists;
import com.hsgene.common.util.basic.JsonUtils;
import com.hsgene.common.util.basic.UUID32;
import com.hsgene.common.util.result.ApiResult;
import com.hsgene.common.util.result.NullObject;
import com.hsgene.common.util.validation.FieldChecker;
import com.hsgene.consumables.constant.GoodsApplyStatus;
import com.hsgene.consumables.domain.v1.GeneticGoods;
import com.hsgene.consumables.domain.v1.GeneticGoodsApply;
import com.hsgene.consumables.dto.peanut.PeanutApplyIdDto;
import com.hsgene.consumables.dto.v1.GoodsApplyOperationDto;
import com.hsgene.consumables.dto.v1.operation.GoodsApplyAddDto;
import com.hsgene.consumables.dto.v1.operation.GoodsApplyModifyDto;
import com.hsgene.consumables.dto.v1.operation.GoodsApplyOperationItemDetailDto;
import com.hsgene.consumables.exception.ConsumablesErrorCode;
import com.hsgene.consumables.persistence.ConsumablesApplyRepository;
import com.hsgene.consumables.persistence.GoodsApplyRepository;
import com.hsgene.consumables.persistence.GoodsRepository;
import com.hsgene.consumables.service.GoodsApplyService;
import com.hsgene.consumables.service.api.GeneratorService;
import com.hsgene.generator.dto.GeneratorDto;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;

/**
 * 耗材申领ServiceImpl
 *
 * @author wangbing
 * @version 1.0, 2018/9/17
 */
@Service
public class GoodsApplyServiceImpl implements GoodsApplyService {

    private final static Logger LOGGER = LoggerFactory.getLogger(GoodsApplyServiceImpl.class);

    @Resource
    private GoodsRepository goodsRepository;

    @Resource
    private ConsumablesApplyRepository applyRepository;

    @Resource
    private GoodsApplyRepository goodsApplyRepository;

    @Resource
    private GeneratorService generatorService;

    @Value("${genetic.testing.goods.apply_no.prefix}")
    private String geneticTestingGoodsApplyNoPrefix;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ApiResult<NullObject> goodsApplyOperation(String groundServantId, GoodsApplyOperationDto operationInfo) {
        FieldChecker.checkEmpty(groundServantId, "groundServantId");

        FieldChecker.checkEmpty(operationInfo.getGoodsApply(), "耗材申领信息");
        GoodsApplyAddDto addDto = JsonUtils.jsonToObject(JsonUtils.objectToJson(operationInfo.getGoodsApply()), new TypeReference<GoodsApplyAddDto>() {
        });
        addDto.check();
        return addGoodsApply(groundServantId, addDto.getGoodsApplyDetails());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ApiResult<NullObject> updateGoodsApply(GoodsApplyModifyDto goodsApplyModifyDto) {
        // 根据id查applyno，再找到所有的apply主键
        PeanutApplyIdDto peanutApplyIdDto = applyRepository.applyIds(goodsApplyModifyDto.getApply_id());
        String groundServantId = peanutApplyIdDto.getGroundServantId();
        List<GoodsApplyOperationItemDetailDto> goodsList = goodsApplyModifyDto.getGoodsApplyDetails();
        // 添加的list
        List<GeneticGoodsApply> applies = Lists.newArrayList();
        String applyNo = peanutApplyIdDto.getApplyNo();
        List<GeneticGoodsApply> appliesUpdate = Lists.newArrayList();
        // 删除多余的
        String[] split = StringUtils.split(goodsApplyModifyDto.getDeleteDetailIds(), ",");
        if (split != null && split.length > 0) {
            goodsApplyRepository.deleteByApplys(split);
        }
        for (GoodsApplyOperationItemDetailDto item : goodsList) {
            GeneticGoods goods = goodsRepository.findById(item.getGoodsId());
            if (goods == null || goods.getDeleteFlag()) {
                return ApiResult.fail(ConsumablesErrorCode.GENETIC_GOODS_NOT_EXISTED, "耗材[" + item.getGoodsName() + "]不存在");
            }
            if (goods.getAmount() < item.getApplyNumber()) {
                return ApiResult.fail(ConsumablesErrorCode.GENETIC_GOODS_AMOUNT_NOT_ENOUGH, "耗材：" + item.getGoodsName() + "库存不足");
            }
            // 申请apply(如果没有即为新增一条)
            if (StringUtils.isEmpty(item.getId())) {
                GeneticGoodsApply apply = buildGeneticGoodsApply(applyNo, groundServantId, item);
                applies.add(apply);
            } else {
                GeneticGoodsApply apply = buildGeneticGoodsApplyUpdate(item);
                appliesUpdate.add(apply);
            }
        }
        // 保存数据
        if (applies.size() > 0) {
            goodsApplyRepository.saveBatch(applies);
        }
        goodsApplyRepository.updateBatch(appliesUpdate);
        return ApiResult.succ();
    }

    /**
     * 新增耗材申领单
     *
     * @param groundServantId 地服id
     * @param goodsList       新申领的耗材列表
     * @return 申领结果
     */
    private ApiResult<NullObject> addGoodsApply(final String groundServantId, List<GoodsApplyOperationItemDetailDto> goodsList) {
        List<GeneticGoodsApply> applies = Lists.newArrayList();

        ApiResult<GeneratorDto> generatorResult = generatorService.numberGenerator(geneticTestingGoodsApplyNoPrefix, null, null);
        if (!generatorResult.isSucc()) {
            LOGGER.error("新增耗材申领单失败：", generatorResult.getDesc());
            return ApiResult.fail(generatorResult.getError());
        }
        String applyNo = generatorResult.getData().getSerialNumber();
        for (GoodsApplyOperationItemDetailDto item : goodsList) {
            GeneticGoods goods = goodsRepository.findById(item.getGoodsId());
            if (goods == null || goods.getDeleteFlag()) {
                return ApiResult.fail(ConsumablesErrorCode.GENETIC_GOODS_NOT_EXISTED, "耗材[" + item.getGoodsName() + "]不存在");
            }
            if (!goods.getName().equals(item.getGoodsName())) {
                LOGGER.error("地服[{}]申请耗材[{}]的名称[{}]与库存[{}]不一致",
                        groundServantId, item.getGoodsId(), item.getGoodsName(), goods.getName());
            }
            if (goods.getAmount() < item.getApplyNumber()) {
                return ApiResult.fail(ConsumablesErrorCode.GENETIC_GOODS_AMOUNT_NOT_ENOUGH, "耗材：" + item.getGoodsName() + "库存不足");
            }
            // 构建申请
            GeneticGoodsApply apply = buildGeneticGoodsApply(applyNo, groundServantId, item);
            applies.add(apply);
        }
        // 保存数据
        goodsApplyRepository.saveBatch(applies);

        return ApiResult.succ();
    }

    /**
     * 构建申请
     *
     * @param groundServantId 地服id
     * @param item            耗材申请项
     * @return 申请
     */
    private GeneticGoodsApply buildGeneticGoodsApply(final String applyNo, final String groundServantId, GoodsApplyOperationItemDetailDto item) {
        GeneticGoodsApply apply = new GeneticGoodsApply();
        apply.setId(UUID32.randomUUIDString());
        apply.setGoodsId(item.getGoodsId());

        apply.setApplyNo(applyNo);
        apply.setApplyAmount(item.getApplyNumber());
        apply.setStatus(GoodsApplyStatus.WAIT_AUDIT.getStatus());
        apply.setGroundServantId(groundServantId);
        apply.setCreateDateTime(new Date());
        apply.setUpdateDateTime(apply.getCreateDateTime());
        apply.setDeleteFlag(false);
        return apply;
    }

    /**
     * 构建申请更新
     *
     * @param item 耗材申请项
     * @return 申请
     */
    private GeneticGoodsApply buildGeneticGoodsApplyUpdate(GoodsApplyOperationItemDetailDto item) {
        GeneticGoodsApply apply = new GeneticGoodsApply();
        apply.setId(item.getId());
        apply.setGoodsId(item.getGoodsId());
        apply.setApplyAmount(item.getApplyNumber());
        apply.setStatus(GoodsApplyStatus.WAIT_AUDIT.getStatus());
        apply.setUpdateDateTime(new Date());
        return apply;
    }
}
